package com.base.service.workflow.service.impl;

import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.base.core.framework.sql.service.impl.SqlBaseServiceImplV1Ext;
import com.base.core.head.constants.CodeResVal;
import com.base.core.head.enums.TaskTypeEnum;
import com.base.service.workflow.dao.TaskDao;
import com.base.service.workflow.entity.SequenceFlowDO;
import com.base.service.workflow.entity.TaskDO;
import com.base.service.workflow.service.SequenceFlowService;
import com.base.service.workflow.service.TaskService;
import com.gitee.magic.core.json.JsonObject;
import com.gitee.magic.framework.head.exception.BusinessException;
import com.gitee.magic.jdbc.persistence.source.jdbc.sqlplus.conditions.query.QueryWrapper;
import com.gitee.magic.jdbc.persistence.source.jdbc.sqlplus.toolkit.StringUtils;
import com.greenpineyu.fel.FelEngine;
import com.greenpineyu.fel.FelEngineImpl;
import com.greenpineyu.fel.context.FelContext;

/**
 * @author start 
 */
@Service("taskService")
public class TaskServiceImpl extends SqlBaseServiceImplV1Ext<TaskDO,Long> 
implements TaskService {

	private TaskDao taskDao;
	@Autowired
	private SequenceFlowService sequenceFlowService;
	
	public TaskServiceImpl(@Qualifier("taskDao")TaskDao taskDao) {
		super(taskDao);
		this.taskDao=taskDao;
	}

	@Override
	public TaskDO getTaskEvent(Long deploymentId,TaskTypeEnum taskType) {
		QueryWrapper wrapper=new QueryWrapper();
		wrapper.eq("deploymentId", deploymentId).eq("taskType", String.valueOf(taskType));
		return get(taskDao.queryForList(wrapper));
	}
	
	@Override
	public TaskDO nextTask(Long taskId, JsonObject variables) {
		List<SequenceFlowDO> sequenceFlows = sequenceFlowService.queryBySourceRefId(taskId);
		TaskDO nextTask = getTargetTask(sequenceFlows);
		FelEngine felEngine = new FelEngineImpl();
		FelContext context = felEngine.getContext();
		for(String key:variables.keySet()) {
			context.set(key,variables.get(key));
		}
		// check next task type is exclusive gateway ?
		while (nextTask.getTaskType() == TaskTypeEnum.EXCLUSIVE_GATEWAY) {
			// reset sequenceFlows when task is exclusive gateway
			sequenceFlows = sequenceFlowService.queryBySourceRefId(nextTask.getId());
			if (variables.length()>0) {
				Iterator<SequenceFlowDO> iterator = sequenceFlows.iterator();
				while (iterator.hasNext()) {
					SequenceFlowDO sequenceFlow = iterator.next();
					String expression = sequenceFlow.getExpression();
					//没有表达式类似于else条件可直接跳过
					if (StringUtils.isEmpty(expression)) {
						continue;
					}
					boolean match = (boolean) felEngine.eval(expression, context);
					// if not match, remove this sequence flow
					if (!match) {
						iterator.remove();
					}
				}
			}
			
			if(sequenceFlows.size()==1) {
				nextTask = getTargetTask(sequenceFlows);
			}else {
				List<SequenceFlowDO> sequences=sequenceFlows.stream()
						.filter(t->!StringUtils.isEmpty(t.getExpression())).toList();
				nextTask = getTargetTask(sequences);
			}
		}
		return nextTask;
	}

	/**
	 * 获取目标流转任务
	 * @param sequenceFlows
	 * @return
	 */
	public TaskDO getTargetTask(List<SequenceFlowDO> sequenceFlows) {
		// 有且只有一条
		if(sequenceFlows.size()!=1) {
			throw new BusinessException(CodeResVal.CODE_10052);
		}
		Long nextTaskId = get(sequenceFlows).getTargetRefId();
		return load(nextTaskId);
	}
	
}
